home *** CD-ROM | disk | FTP | other *** search
/ Scene Storm / Scene Storm - Volume 1.iso / coding / c / nullmodem / src / device.c < prev    next >
C/C++ Source or Header  |  1995-12-18  |  9KB  |  322 lines

  1. #include "defs.h"
  2. #include "protos.h"
  3.  
  4. extern char DeviceName[];
  5. extern UBYTE S_Default[];
  6.  
  7. struct TagItem ModemProcTagList[] = {
  8.     {   NP_Entry,       modem_task      },
  9.     {   NP_Name,        DeviceName      },
  10.     {   NP_Priority,    MODEM_TASK_PRI  },
  11.     {   NP_StackSize,   MODEM_STACK_SIZE},
  12.     {   TAG_DONE,       TAG_DONE        },
  13. };
  14.  
  15. /*
  16.  *  Creates and Initialises a Modem
  17.  */
  18. struct NullModem *CreateModem(ULONG modemnum)
  19. {
  20. struct NullModem *modem;
  21.  
  22.     if( modem = AllocMem(sizeof(struct NullModem), MEMF_PUBLIC | MEMF_CLEAR) ) {
  23.  
  24.         if( modem->nm_Unit[0] = AllocMem(sizeof(struct NullUnit), MEMF_PUBLIC | MEMF_CLEAR) ) {
  25.  
  26.             if( modem->nm_Unit[1] = AllocMem(sizeof(struct NullUnit), MEMF_PUBLIC | MEMF_CLEAR) ) {
  27.  
  28.                 if( OpenDevice(TIMERNAME, UNIT_VBLANK, (struct IORequest *)&modem->nm_Timerequest, 0) == 0 ) {
  29.                 struct Library *DOSBase;
  30.  
  31.                     if( DOSBase = OpenLibrary("dos.library",36) ) {
  32.                     struct Process *pr = CreateNewProc(ModemProcTagList);
  33.  
  34.                         CloseLibrary(DOSBase);
  35.  
  36.                         if( pr ) {
  37.                         int i;
  38.  
  39.                             for( i = 0 ; i < 2 ; i++ ) {
  40.                             struct NullUnit *unit = modem->nm_Unit[i];
  41.                             int j;
  42.  
  43.                                 unit->u_Readptr = unit->u_Buffer;
  44.                                 NewList((struct List *)&unit->u_Readlist);
  45.  
  46.                                 unit->u_Writeptr = unit->u_Buffer;
  47.                                 NewList((struct List *)&unit->u_Writelist);
  48.  
  49.                                 unit->u_Unitnum = i;
  50.                                 unit->u_Modem = modem;
  51.  
  52.                                 for( j = 0 ; j < 64 ; j++ )
  53.                                     unit->u_SReg[j] = S_Default[j];
  54.  
  55.                             }
  56.  
  57.                             pr->pr_Task.tc_UserData = modem;    /* So the modem Process can find its data */
  58.                             modem->nm_Taskptr = &pr->pr_Task;   /* and so everybody else knows where to signal */
  59.  
  60.                             InitSemaphore(&modem->nm_Semaphore);
  61.  
  62.                             modem->nm_Modemnum = modemnum;
  63.                             DevBase->b_Modem[modemnum] = modem;
  64.  
  65.                             DevBase->b_Lib.lib_OpenCnt++;       /* hold the device for the task */
  66.  
  67.                             return(modem);  /* gotit */
  68.                         }
  69.                     }
  70.                     CloseDevice( (struct IORequest *)&modem->nm_Timerequest );
  71.                 }
  72.                 FreeMem(modem->nm_Unit[1], sizeof(struct NullUnit));
  73.             }
  74.             FreeMem(modem->nm_Unit[0], sizeof(struct NullUnit));
  75.         }
  76.         FreeMem(modem, sizeof(struct NullModem));
  77.     }
  78.     return(NULL);
  79. }
  80.  
  81. /*
  82.  *  open device (in a Forbid)
  83.  *
  84.  *      unitnum:    D0
  85.  *      flags:      D1
  86.  *      iob:        A1
  87.  *
  88.  */
  89. struct NullBase *
  90. DevOpen( __D0 ULONG unitnum,
  91.          __D1 ULONG flags,
  92.          __A1 struct IOExtSer *iob)
  93. {
  94. struct NullBase *db = DevBase;
  95. ULONG modemnum = unitnum >> 1;
  96.  
  97.     db->b_Lib.lib_OpenCnt++;    /* fake opener so we don't get expunged */
  98.  
  99.     /*
  100.      *  set fail conditions as default..
  101.      */
  102.     iob->IOSer.io_Error = IOERR_OPENFAIL;
  103.     iob->IOSer.io_Device = (struct Device *)-1;     /* trashed */
  104.  
  105.     /*
  106.      *  range check
  107.      */
  108.     if( modemnum < MODEM_UNITS ) {
  109.     struct NullModem *modem = db->b_Modem[modemnum];
  110.  
  111.         if( modem || (modem = CreateModem(modemnum)) ) {
  112.         struct NullUnit *unit = modem->nm_Unit[unitnum & 1];
  113.  
  114.             if( (unit->u_OpenCnt == 0) || (unit->u_Flags & SERF_SHARED & iob->io_SerFlags) ) {
  115.  
  116.                 /* open the unit */
  117.                 if( unit->u_OpenCnt++ == 0 ) {
  118.                     unit->u_Flags = iob->io_SerFlags & SERF_SHARED;
  119.                     unit->u_SReg[SREG_STATE] = STATE_COMMAND;
  120.                     unit->u_SReg[SREG_CMD_COUNT] = 0;
  121.                 }
  122.  
  123.                 /* open the modem */
  124.                 modem->nm_OpenCnt++;
  125.  
  126.                 /* open the device */
  127.                 db->b_Lib.lib_OpenCnt++;
  128.  
  129.                 /* tell them all about it */
  130.                 iob->IOSer.io_Device = (struct Device *)db; /* restored */
  131.                 iob->IOSer.io_Unit = unit;
  132.                 iob->IOSer.io_Error = 0;
  133.                 iob->IOSer.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
  134.  
  135.                 /* prefs? pah ;-) */
  136.                 iob->io_CtlChar = SER_DEFAULT_CTLCHAR;
  137.                 iob->io_RBufLen = UNIT_BUF_SIZE;
  138.                 iob->io_Baud = 9600;
  139.  
  140.                 dprintf(unit, 2, "OpenDevice\n");
  141.             }
  142.         }
  143.     }
  144.  
  145.     db->b_Lib.lib_OpenCnt--;    /* end of fake opener */
  146.  
  147.     return(iob->IOSer.io_Error);
  148. }
  149.  
  150.  
  151. /*
  152.  *  close device (in a Forbid)
  153.  *
  154.  *      iob:    A1
  155.  *
  156.  *  returns the Segment pointer if the device is to be unloaded, NULL
  157.  *  otherwise -- we always return NULL, because the task takes care of
  158.  *  its own cleanup, and we can't unload until then
  159.  */
  160. APTR
  161. DevClose(__A1 struct IOExtSer *iob)
  162. {
  163. struct NullBase *db = DevBase;
  164. struct NullUnit *unit = (struct NullUnit *)iob->IOSer.io_Unit;
  165. struct NullModem *modem = unit->u_Modem;
  166.  
  167.     /*
  168.      *  make sure we don't take anything with this iob again
  169.      */
  170.     iob->IOSer.io_Unit = (struct Unit *)-1;
  171.     iob->IOSer.io_Device = (struct Device *)-1;
  172.  
  173.     dprintf(unit,2,"CloseDevice\n");
  174.  
  175.     unit->u_OpenCnt--;
  176.     modem->nm_OpenCnt--;
  177.     db->b_Lib.lib_OpenCnt--;
  178.  
  179.     /*
  180.      *  DTR hangup if the unit is empty
  181.      */
  182.     if( unit->u_OpenCnt == 0 ) {
  183.         dprintf(unit,3,"DTR drop signalled\n");
  184.         Signal(modem->nm_Taskptr, SIGBREAKF_CTRL_D);
  185.     }
  186.  
  187.     /*
  188.      *  and Zap the modem if nobody is left
  189.      */
  190.     if( modem->nm_OpenCnt == 0 ) {
  191.         dprintf(unit,3,"Task Exit signal sent\n");
  192.         Signal(modem->nm_Taskptr, SIGBREAKF_CTRL_E);
  193.         db->b_Modem[modem->nm_Modemnum] = NULL;
  194.     }
  195.  
  196.     return(NULL);
  197. }
  198.  
  199.  
  200. /*
  201.  *  device Expunge (in a Forbid)
  202.  *
  203.  *  no arguments
  204.  *
  205.  *  returns segment passed to Init if we want to expunge, NULL otherwise
  206.  *
  207.  */
  208. APTR
  209. DevExpunge(void)
  210. {
  211. struct NullBase *db = DevBase;
  212. APTR dseg = db->b_Segment;
  213.  
  214.     /*
  215.      *  but not yet if we are still open!
  216.      */
  217.     if( db->b_Lib.lib_OpenCnt ) {
  218.         return(NULL);
  219.     }
  220.  
  221.     /*
  222.      *  bye bye
  223.      */
  224.     Remove( &db->b_Lib.lib_Node );
  225.     FreeMem((UBYTE *)db - db->b_Lib.lib_NegSize, db->b_Lib.lib_NegSize + db->b_Lib.lib_PosSize);
  226.     return(dseg);
  227. }
  228.  
  229. /*
  230.  * device Reserved  no arguments, return NULL
  231.  *                  (reserved for future use by C=)
  232.  *
  233.  */
  234. ULONG
  235. DevReserved(void)
  236. {
  237.     return(NULL);
  238. }
  239.  
  240.  
  241. /*
  242.  *  device BeginIO
  243.  *
  244.  *  iob:    a1
  245.  *
  246.  */
  247.  
  248. void
  249. DevBeginIO(__A1 struct IOExtSer *iob)
  250. {
  251. struct NullUnit *unit = (struct NullUnit *)iob->IOSer.io_Unit;
  252. static struct IOExtSer *(*cmd_table[])(struct IOExtSer *) = {
  253.     cmd_invalid,
  254.     cmd_reset,
  255.     cmd_read,
  256.     cmd_write,
  257.     cmd_update,
  258.     cmd_clear,
  259.     cmd_stop,
  260.     cmd_start,
  261.     cmd_flush,
  262.     sdcmd_query,
  263.     sdcmd_break,
  264.     sdcmd_setparams,
  265.     cmd_invalid,
  266.     cmd_invalid,
  267.     cmd_invalid,
  268.     cmd_invalid,
  269.     asdg_dtrcontrol,
  270. };
  271.  
  272.     dprintf(unit, 3, "BeginIO (Cmd #%ld)\n",iob->IOSer.io_Command);
  273.  
  274.     iob->IOSer.io_Message.mn_Node.ln_Type = NT_MESSAGE;
  275.  
  276.     if( iob->IOSer.io_Command >= arraysize(cmd_table) ) {
  277.         iob->IOSer.io_Error = IOERR_NOCMD;
  278.     }
  279.     else {
  280.         iob->IOSer.io_Error = 0;
  281.         iob->IOSer.io_Actual = 0;
  282.  
  283.         iob = (*cmd_table[iob->IOSer.io_Command])(iob); /* do the command */
  284.     }
  285.  
  286.     if( iob ) /*  read & write return NULL if the request was queued */
  287.         if( (iob->IOSer.io_Flags & IOF_QUICK) == 0 )
  288.             ReplyMsg(&iob->IOSer.io_Message);
  289. }
  290.  
  291.  
  292. /*
  293.  * device AbortIO
  294.  *
  295.  *   iob:    a1
  296.  *
  297.  */
  298. ULONG
  299. DevAbortIO(__A1 struct IOExtSer *iob)
  300. {
  301. struct NullUnit *unit = (struct NullUnit *)iob->IOSer.io_Unit;
  302.  
  303.     ObtainSemaphore(&unit->u_Modem->nm_Semaphore);
  304.  
  305.     /* we only abort if the message hasn't been done already.. */
  306.     /* it could have completed while we were waiting for the Semaphore */
  307.  
  308.     if( iob->IOSer.io_Message.mn_Node.ln_Type != NT_REPLYMSG && (iob->IOSer.io_Flags & IOF_QUICK) == 0 ) {
  309.         Remove(&iob->IOSer.io_Message.mn_Node);
  310.         iob->IOSer.io_Error = IOERR_ABORTED;
  311.         ReplyMsg(&iob->IOSer.io_Message);
  312.         dprintf(unit, 1,"AbortIO (aborted)\n");
  313.     }
  314.     else {
  315.         dprintf(unit, 1,"AbortIO (already complete)\n");
  316.     }
  317.  
  318.     ReleaseSemaphore(&unit->u_Modem->nm_Semaphore);
  319.  
  320.     return(iob->IOSer.io_Error);
  321. }
  322.